using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Threading;

namespace SpoonCore.Simulation
{
	internal class RealSimulation : ISimulation
	{
		private const int MinWait = 10;
		private const int MaxWait = 10;
		private const int StartCount = 10;

		private Thread _simulationThread;
		private List<SpoonClient> _clientList = new List<SpoonClient>();
		private Semaphore _sem = new Semaphore(1, 1);
		private SpoonClient _server = new SpoonClient(1000);

		public RealSimulation()
		{
			_simulationThread = new Thread(new ThreadStart(Sim));
		}

		private void Sim()
		{
			Random rand = new Random();
			while (true)
			{
				_sem.WaitOne();
				if (rand.NextDouble() >= 0.5)
				{
					// Add
					SpoonClient client = new SpoonClient();
					client.AddBootstrap(new IPEndPoint(IPAddress.Loopback, 1000));
					client.Start();
					_clientList.Add(client);
					Console.WriteLine("Add: " + client);
				}
				else
				{
					// Remove
					if (_clientList.Count > 0)
					{
						int pos = rand.Next(_clientList.Count);
						_clientList[pos].Dispose();
						Console.WriteLine("Remove: " + _clientList[pos]);
						_clientList.RemoveAt(pos);
					}
				}
				_sem.Release();
				Thread.Sleep(rand.Next(MinWait * 1000, MaxWait * 1000));
			}
		}

		public void Pause()
		{
			_sem.WaitOne();
		}

		public void Resume()
		{
			_sem.Release();
		}

		public List<SpoonClient> Clients
		{
			get
			{
				List<SpoonClient> res = new List<SpoonClient>();
				res.AddRange(_clientList);
				res.Add(_server);
				return res;
			}
		}

		public void Run()
		{
			_server.Start();

			Thread.Sleep(250);

			for (int x = 0; x < StartCount; x++)
			{
				SpoonClient client = new SpoonClient();
				client.AddBootstrap(new IPEndPoint(IPAddress.Loopback, 1000));
				client.Start();
				_clientList.Add(client);

				//Thread.Sleep(25);
				Console.WriteLine(client.Id);
			}

			Console.WriteLine("Inizialisation complete");

			Thread.Sleep(5000);

			// Add
			/*SpoonClient cl = new SpoonClient();
			cl.AddBootstrap(new IPEndPoint(IPAddress.Loopback, 1000));
			cl.Start();
			_clientList.Add(cl);
			Console.WriteLine("Add: " + cl);*/

			// Remove
			/*for (int x = 0; x < 1; x++)
			{
				int pos = new Random().Next(_clientList.Count);
				_clientList[pos].Dispose();
				Console.WriteLine("Remove: " + _clientList[pos]);
				_clientList.RemoveAt(pos);
			}
			Console.ReadLine();*/
			
			_simulationThread.Start();

			Console.WriteLine("Press enter to abort...");
			Console.ReadLine();

			_simulationThread.Abort();
			_simulationThread.Interrupt();
			_simulationThread.Join();

			// Shutdown test
			foreach (SpoonClient client in _clientList)
			{
				client.Dispose();
			}

			_server.Dispose();
		}
	}
}